/*
泛型和类型擦除的写法

*/


#include <iostream>
#include <string>
#include <vector>
#include <functional>
#include <unordered_map>
#include <memory>
#include <mutex>

class EventBus {
public:
    // 单例模式
    static EventBus& getInstance() {
        static EventBus instance;
        return instance;
    }

    // 订阅事件
    template <typename EventType>
    void subscribe(const std::string& event, std::function<void(const EventType&)> callback) {
        std::lock_guard<std::mutex> lock(m_mutex);
        listeners[event].push_back([callback](const void* data){
            callback(*static_cast<const EventType*>(data));
        });
    }

    template <typename EventType>
    void subscribe(std::function<void(const EventType&)> callback) {
        std::lock_guard<std::mutex> lock(m_mutex);
        listeners[typeid(EventType).name()].push_back([callback](const void* data){
            std::cout << "Event type: " << typeid(EventType).name() << std::endl;
            callback(*static_cast<const EventType*>(data));
        });
    }

    // 发布事件
    template <typename EventType>
    void publish(const std::string event, const EventType& data) {
        std::vector<std::function<void(const void*)>> callbacks;
        {
            std::lock_guard<std::mutex> lock(m_mutex);
            auto it = listeners.find(event);
            if (it != listeners.end()) callbacks = it->second;
        }
        for (auto& callback : callbacks) {
            callback(&data);
        }
    }

    // 发布事件
    template <typename EventType>
    void publish(const EventType& event) {
        std::lock_guard<std::mutex> lock(m_mutex);
        auto& callbacks = listeners[typeid(EventType).name()];
        for (auto& callback : callbacks) {
            callback(&event);
        }
    }

    // 取消订阅
    template <typename EventType>
    void unsubscribe(std::function<void(const EventType&)> callback) {

    }
private:
    EventBus() = default;
    std::mutex  m_mutex;
    std::unordered_map<std::string, std::vector<std::function<void(const void*)>>> listeners;

};

class TestEvent {
public:
    static int count;
    std::string who_name;
    TestEvent(std::string who_name) : who_name(who_name) {
        count++;
    }
};
int TestEvent::count = 0;
int main() { 
    EventBus& bus = EventBus::getInstance();
    
    bus.subscribe<TestEvent>("test_event", [](const TestEvent& event) {
        std::cout <<event.who_name <<" testEvent times: " << event.count << std::endl;
    });


    TestEvent event("ljq");
    bus.publish("test_event", event);

    TestEvent event2("ljq2");
    bus.publish("test_event", event2);

    bus.subscribe<TestEvent>([](const TestEvent& event) {
        std::cout <<event.who_name <<" testEvent times: " << event.count << std::endl;
    });

    TestEvent event3("ljq3");
    bus.publish(event3);
}


